package com.ailot.cloud.upms.api.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.ailot.cloud.upms.api.mapper.SysMenuMapper;
import com.ailot.cloud.upms.api.mapper.SysRoleMapper;
import com.ailot.cloud.upms.api.mapper.SysUserMapper;
import com.ailot.cloud.upms.api.service.SysUserRoleService;
import com.ailot.cloud.upms.api.service.SysUserService;
import com.ailot.cloud.upms.common.dto.JwtUserDTO;
import com.ailot.cloud.upms.common.dto.SysUserDTO;
import com.ailot.cloud.upms.common.entity.SysMenu;
import com.ailot.cloud.upms.common.entity.SysUser;
import com.ailot.cloud.upms.common.entity.SysUserRole;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 用户管理
 */
@Slf4j
@Service
@AllArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    private final SysMenuMapper sysMenuMapper;
    private final SysRoleMapper sysRoleMapper;
    private final SysUserRoleService sysUserRoleService;


    /**
     * 添加用户
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addUser(SysUserDTO sysUserDTO) {
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        SysUser sysUser = new SysUser();
        BeanUtil.copyProperties(sysUserDTO, sysUser);
        sysUser.setPassword(passwordEncoder.encode(sysUserDTO.getPassword()));
        baseMapper.insert(sysUser);
        sysUserDTO.setId(sysUser.getId());
        return saveRole(sysUserDTO);
    }

    @Override
    public Boolean updateUser(SysUserDTO sysUserDto) {
        SysUser sysUser = new SysUser();
        BeanUtil.copyProperties(sysUserDto, sysUser);
        sysUser.setUpdateTime(LocalDateTime.now());
        sysUser.setPassword(null);
        this.updateById(sysUser);
        sysUserRoleService.remove(Wrappers.<SysUserRole>lambdaQuery()
                .eq(SysUserRole::getUserId, sysUserDto.getId()));

        return saveRole(sysUserDto);
    }

    @NotNull
    private Boolean saveRole(SysUserDTO sysUserDTO) {
        List<String> roleIds = sysUserDTO.getRoleIds();
        if (CollectionUtil.isNotEmpty(roleIds)) {
            List<SysUserRole> userRoleList = roleIds.stream().map(roleId -> {
                SysUserRole userRole = new SysUserRole();
                userRole.setUserId(sysUserDTO.getId());
                userRole.setRoleId(roleId);
                return userRole;
            }).collect(Collectors.toList());
            return sysUserRoleService.saveBatch(userRoleList);
        } else {
            log.error("用户角色为空");
            return false;
        }
    }

    /**
     * 查询用户信息，角色，权限
     */
    @Override
    public JwtUserDTO getUserDetail(SysUser sysUser) {
        JwtUserDTO jwtUserDTO = new JwtUserDTO();
        jwtUserDTO.setSysUser(sysUser);

        List<String> roleIds = sysRoleMapper.getRoleIdsByUserId(sysUser.getId());
        jwtUserDTO.setRoles(ArrayUtil.toArray(roleIds, String.class));

        Set<String> permissions = new HashSet<>();
        roleIds.forEach(roleId -> {
            List<String> permissionList = sysMenuMapper.getMenusByRoleId(roleId)
                    .stream()
                    .filter(menuVo -> StrUtil.isNotEmpty(menuVo.getPermission()))
                    .map(SysMenu::getPermission)
                    .collect(Collectors.toList());
            permissions.addAll(permissionList);
        });
        jwtUserDTO.setPermissions(ArrayUtil.toArray(permissions, String.class));
        return jwtUserDTO;
    }

    @Override
    public IPage pageUser(Page page, SysUserDTO sysUserDTO) {
        return baseMapper.pageUser(page, sysUserDTO);
    }

}
